/**
 *    Copyright (C) 2008, 2009  Victor Smirnov <aist11@gmail.com>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along
 *    with this program; if not, write to the Free Software Foundation, Inc.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *    See LICENSE.exceptions in the root folder of this project for possible
 *    exceptions
 *
 */

#ifndef _CUBEFS_CORE_API_REFLECTION_FACTORY_HPP
#define	_CUBEFS_CORE_API_REFLECTION_FACTORY_HPP

#include <cubefs/api/macro.hpp>

#include <cubefs/api/reflection/factory.hpp>

#include <cubefs/core/api/reflection/type.hpp>
#include <cubefs/core/api/reflection/value.hpp>
#include <cubefs/core/api/reflection/number.hpp>
#include <cubefs/core/api/reflection/list.hpp>

#include <cubefs/api/tools/version.hpp>
namespace cubefs    {
namespace api       {

template <typename Interface>
class CoreFactoryImplT: public TypedImplT<Interface> {
	typedef CoreFactoryImplT<Interface> 	Me;
	typedef TypedImplT<Interface>			Base;
public:

	CoreFactoryImplT() {
		type_system_ = new TypeSystemImpl();
	}

	virtual ~CoreFactoryImplT() throw() {
		delete type_system_;
	}

	virtual ListOfTyped* CreateListOfTyped(Int size) {
		return size == -1 ? new ListOfTypedImpl() : new ListOfTypedImpl(size);
	}

	virtual StaticListOfTyped* CreateStaticListOfTyped() {
		return new StaticListOfTypedImpl();
	}

	virtual ListOfTypes* CreateListOfTypes(Int size = -1) {
		return size == -1 ? new ListOfTypesImpl() : new ListOfTypesImpl(size);
	}

	virtual ListOfStrings* CreateListOfStrings(Int size = -1) {
		return size == -1 ? new ListOfStringsImpl() : new ListOfStringsImpl(size);
	}

	virtual ListOfBigInt* CreateListOfBigInt(Int size = -1)	{
		return size == -1 ? new ListOfBigIntImpl() : new ListOfBigIntImpl(size);
	}




	virtual ByteNumber* Create(Byte value) {
		return new TypedNumberImpl<Byte>(value);
	}

	virtual UByteNumber* Create(UByte value) {
		return new TypedNumberImpl<UByte>(value);
	}

	virtual ShortNumber* Create(Short value) {
		return new TypedNumberImpl<Short>(value);
	}

	virtual UShortNumber* Create(UShort value) {
		return new TypedNumberImpl<UShort>(value);
	}

	virtual IntNumber* Create(Int value) {
		return new TypedNumberImpl<Int>(value);
	}

	virtual UIntNumber* Create(UInt value) {
		return new TypedNumberImpl<UInt>(value);
	}

	virtual BigIntNumber* Create(BigInt value) {
		return new TypedNumberImpl<BigInt>(value);
	}

	virtual FloatNumber* Create(float value) {
		return new TypedNumberImpl<float>(value);
	}

	virtual DoubleNumber* Create(double value) {
		return new TypedNumberImpl<double>(value);
	}

	virtual TypedIDValue* Create(const IDValue &id) {
		return new TypedValueImpl<IDValue>(id);
	}

	virtual TypedIDValue* 	CreateIDValue(StringRef id) {
		return new TypedValueImpl<IDValue>(id);
	}

	virtual StringValue* Create(StringRef str) {
		return new TypedValueImpl<String>(str);
	}

	virtual BooleanValue* Create(bool value) {
		return new TypedValueImpl<bool>(value);
	}

	virtual VersionValue* Create(const Version& version){
		return new TypedValueImpl<Version>(version);
	}

	virtual VersionValue* 	CreateVersion(StringRef ver) {
		return new TypedValueImpl<Version>(ver);
	}

	virtual TypeSystem*	GetCoreTypeSystem() {
		return type_system_;
	}


	static void InitType() {
		type_ = new AbstractType(TypeNameFactory<Interface>::name(), Typed::MyType());
	}

	static void InitOperations() {
		AbstractType *type = static_cast<AbstractType*>(type_);

		type->AddOperation(new BasicOperation<Typed* (Me::*)(Int), ListOfTyped* (Me::*)(Int)>(type, ListOfTyped::MyType(), "CreateListOfTyped", "size", &Me::CreateListOfTyped));
		type->AddOperation(new BasicOperation<Typed* (Me::*)(), StaticListOfTyped* (Me::*)()>(type, StaticListOfTyped::MyType(), "CreateStaticListOfTyped", &Me::CreateStaticListOfTyped));

		type->AddOperation(new BasicOperation<Typed* (Me::*)(Int), ListOfTypes* (Me::*)(Int)>(type, ListOfTypes::MyType(), "CreateListOfTypes", "size", &Me::CreateListOfTypes));

		type->AddOperation(new BasicOperation<Typed* (Me::*)(Int), ListOfStrings* (Me::*)(Int)>(type, ListOfStrings::MyType(), "CreateListOfStrings", "size", &Me::CreateListOfStrings));
		type->AddOperation(new BasicOperation<Typed* (Me::*)(Int), ListOfBigInt* (Me::*)(Int)>(type, ListOfBigInt::MyType(), "CreateListOfBigInt", "size", &Me::CreateListOfBigInt));

		type->AddOperation(new BasicOperation<Typed* (Me::*)(Byte), ByteNumber* (Me::*)(Byte)>(type, ByteNumber::MyType(), "CreateByteNumber", "value", &Me::Create));
		type->AddOperation(new BasicOperation<Typed* (Me::*)(UByte), UByteNumber* (Me::*)(UByte)>(type, UByteNumber::MyType(), "CreateUByteNumber", "value", &Me::Create));

		type->AddOperation(new BasicOperation<Typed* (Me::*)(Short), ShortNumber* (Me::*)(Short)>(type, ShortNumber::MyType(), "CreateShortNumber", "value", &Me::Create));
		type->AddOperation(new BasicOperation<Typed* (Me::*)(UShort), UShortNumber* (Me::*)(UShort)>(type, UShortNumber::MyType(), "CreateUShortNumber", "value", &Me::Create));

		type->AddOperation(new BasicOperation<Typed* (Me::*)(Int), IntNumber* (Me::*)(Int)>(type, IntNumber::MyType(), "CreateIntNumber", "value", &Me::Create));
		type->AddOperation(new BasicOperation<Typed* (Me::*)(UInt), UIntNumber* (Me::*)(UInt)>(type, UIntNumber::MyType(), "CreateUIntNumber", "value", &Me::Create));

		type->AddOperation(new BasicOperation<Typed* (Me::*)(BigInt), BigIntNumber* (Me::*)(BigInt)>(type, BigIntNumber::MyType(), "CreateBigIntNumber", "value", &Me::Create));

		type->AddOperation(new BasicOperation<Typed* (Me::*)(float), FloatNumber* (Me::*)(float)>(type, FloatNumber::MyType(), "CreateFloatNumber", "value", &Me::Create));
		type->AddOperation(new BasicOperation<Typed* (Me::*)(double), DoubleNumber* (Me::*)(double)>(type, DoubleNumber::MyType(), "CreateDoubleNumber", "value", &Me::Create));

		type->AddOperation(new BasicOperation<Typed* (Me::*)(IDValue), TypedIDValue* (Me::*)(const IDValue&)>(type, TypedIDValue::MyType(), "CreateIDValue", "value", &Me::Create));
		type->AddOperation(new BasicOperation<Typed* (Me::*)(bool), BooleanValue* (Me::*)(bool)>(type, BooleanValue::MyType(), "CreateBooleanValue", "value", &Me::Create));
	}

	CUBEFS_DECLARE_REFLECTION;

private:
	TypeSystem* type_system_;
};

template <typename Interface>
Type* CoreFactoryImplT<Interface>::type_ 				= NULL;

//template <typename Interface>
//TypeSystem* CoreFactoryImplT<Interface>::type_system_ 	= NULL;

typedef CoreFactoryImplT<CoreFactory>					CoreFactoryImpl;

}
}

#endif
